#include "yunw_mesh_service.h"
#include <stdio.h>
#include <libubus.h>
#include <libubox/uloop.h>
#include <libubox/list.h>
#include <libubox/blobmsg_json.h>
#include <cjson/cJSON.h>
#include "comm.h"
#include "data_type.h"

extern t_RunCfg runCfg;
struct blob_buf yunw_mb;

// 定义策略表
static const struct blobmsg_policy yunw_data_policy[] = {
    [0] = { .name = "version",    .type = BLOBMSG_TYPE_STRING },
    [1] = { .name = "iface",    .type = BLOBMSG_TYPE_STRING },
    [2] = { .name = "mac",    .type = BLOBMSG_TYPE_STRING },
    [3] = { .name = "ip",    .type = BLOBMSG_TYPE_STRING },
    [4] = { .name = "wifimode",    .type = BLOBMSG_TYPE_INT32 },
    [5] = { .name = "channel",    .type = BLOBMSG_TYPE_INT32 },
    [6] = { .name = "freq",    .type = BLOBMSG_TYPE_INT32 },
    [7] = { .name = "rxinfomsgs",   .type = BLOBMSG_TYPE_ARRAY },
    [8] = { .name = "meshmpath",   .type = BLOBMSG_TYPE_ARRAY },
};

static const struct blobmsg_policy rxinfomsgs_policy[] = {
    [0] = { .name = "mac", .type = BLOBMSG_TYPE_STRING },
    [1] = { .name = "rssi0",    .type = BLOBMSG_TYPE_INT32 },
    [2] = { .name = "rssi1",    .type = BLOBMSG_TYPE_INT32 },
    [3] = { .name = "quality",    .type = BLOBMSG_TYPE_INT32 },
    [4] = { .name = "rate", .type = BLOBMSG_TYPE_STRING },
};

static const struct blobmsg_policy meshmpath_policy[] = {
    [0] = { .name = "dstmac",    .type = BLOBMSG_TYPE_STRING },
    [1] = { .name = "dstip", .type = BLOBMSG_TYPE_STRING },
    [2] = { .name = "nextmac", .type = BLOBMSG_TYPE_STRING },
    [3] = { .name = "nextip", .type = BLOBMSG_TYPE_STRING },
};

static void ubus_yunw_callback(struct ubus_request *req, int type, struct blob_attr *msg) {
    if (!msg) return;
    struct blob_attr *tb[9];
    blobmsg_parse(yunw_data_policy, ARRAY_SIZE(yunw_data_policy), tb, blob_data(msg), blob_len(msg));
    uint8_t modelNumber[50]={0};
    cJSON *root = cJSON_CreateObject();
    EP_JSON_SET_STR(root, "sn", runCfg.sn);
    EP_JSON_SET_INT(root, "loraId", runCfg.lora_addr);
    EP_JSON_SET_INT(root, "dataType", 4);
    EP_JSON_SET_INT(root, "version", 1);
    cJSON *meshData = cJSON_CreateObject();
    if(tb[0]){
        EP_JSON_SET_STR(meshData, "version", blobmsg_get_string(tb[0]));
    }
    if(tb[1]){
        EP_JSON_SET_STR(meshData, "iface", blobmsg_get_string(tb[1]));
    }
    if(tb[2]){
        EP_JSON_SET_STR(meshData, "mac", blobmsg_get_string(tb[2]));
    }
    if(tb[3]){
        EP_JSON_SET_STR(meshData, "ip", blobmsg_get_string(tb[3]));
    }
    if(tb[4]){
        EP_JSON_SET_INT(meshData, "wifimode", blobmsg_get_u32(tb[4]));
    }
    if(tb[5]){
        EP_JSON_SET_INT(meshData, "channel", blobmsg_get_u32(tb[5]));
    }
    if(tb[6]){
        EP_JSON_SET_INT(meshData, "freq", blobmsg_get_u32(tb[6]));
    }

    if(tb[7]){
        struct blob_attr *rxinfomsgs;
        size_t rem;
        cJSON *array = cJSON_CreateArray();
        blobmsg_for_each_attr(rxinfomsgs, tb[7], rem) {
            struct blob_attr *tb_rxinfomsg[5];
            blobmsg_parse(rxinfomsgs_policy, ARRAY_SIZE(rxinfomsgs_policy), tb_rxinfomsg, blobmsg_data(rxinfomsgs), blobmsg_data_len(rxinfomsgs));


            cJSON *rxinfomsg = cJSON_CreateObject();
            if (tb_rxinfomsg[0]) {
                EP_JSON_SET_STR(rxinfomsg, "mac", blobmsg_get_string(tb_rxinfomsg[0]));
            }
            if (tb_rxinfomsg[1]) {
                EP_JSON_SET_INT(rxinfomsg, "rssi0", blobmsg_get_u32(tb_rxinfomsg[1]));
            }
            if (tb_rxinfomsg[2]) {
                EP_JSON_SET_INT(rxinfomsg, "rssi1", blobmsg_get_u32(tb_rxinfomsg[2]));
            }
            if (tb_rxinfomsg[3]) {
                EP_JSON_SET_INT(rxinfomsg, "quality", blobmsg_get_u32(tb_rxinfomsg[3]));
            }
            if (tb_rxinfomsg[4]) {
                EP_JSON_SET_STR(rxinfomsg, "rxbit", blobmsg_get_string(tb_rxinfomsg[4]));
            }
            
            cJSON_AddItemToArray(array, rxinfomsg);
        }
        cJSON_AddItemToObject(meshData,"rxinfomsgs",array);

    }
    if(tb[8]){
        struct blob_attr *meshmpath;
        size_t rem;
        cJSON *array = cJSON_CreateArray();
        blobmsg_for_each_attr(meshmpath, tb[8], rem) {
            struct blob_attr *tb_meshmpath[4];
            blobmsg_parse(meshmpath_policy, ARRAY_SIZE(meshmpath_policy), tb_meshmpath, blobmsg_data(meshmpath), blobmsg_data_len(meshmpath));


            cJSON *meshmpath_json = cJSON_CreateObject();
            if (tb_meshmpath[0]) {
                EP_JSON_SET_STR(meshmpath_json, "dstmac", blobmsg_get_string(tb_meshmpath[0]));
            }
        
            if (tb_meshmpath[1]) {
                EP_JSON_SET_STR(meshmpath_json, "dstip", blobmsg_get_string(tb_meshmpath[1]));
            }
            if (tb_meshmpath[2]) {
                EP_JSON_SET_STR(meshmpath_json, "nextmac", blobmsg_get_string(tb_meshmpath[2]));
            }
            if (tb_meshmpath[3]) {
                EP_JSON_SET_STR(meshmpath_json, "nextip", blobmsg_get_string(tb_meshmpath[3]));
            }
            cJSON_AddItemToArray(array, meshmpath_json);
        }
        cJSON_AddItemToObject(meshData,"meshmpath",array);

    }
    cJSON_AddItemToObject(root,"data",meshData);
    char *str = cJSON_Print(root);
    printf("%s\n", str);
    send_data_to_mqtt(str);
    cJSON_Delete(root);
}

int read_yunw_status_data() {
    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "ubus connect failed\n");
        return -1;
    }
    uint32_t obj_id;
    if (ubus_lookup_id(ctx, "sihan.mesh.yunw", &obj_id) != 0) {
        fprintf(stderr, "lookup failed\n");
        ubus_free(ctx);
        return -1;
    }
    
    blob_buf_init(&yunw_mb, 0);
    //设置参数，如：{"action":"status"}
    // blobmsg_add_string(&b, "action", "status");
    
    // 需要事件循环（此处简化为等待）
    if (ubus_invoke(ctx, obj_id, "status", yunw_mb.head, ubus_yunw_callback, NULL, 3000) != 0) {
        fprintf(stderr, "invoke failed\n");
    }
    blob_buf_free(&yunw_mb);
    ubus_free(ctx);
    return 0;
}

//接收LoRa数据的线程
void *yunw_mesh_worker(void *param)
{
    while (1)
    {
        read_yunw_status_data();
        sleep(5 * 60);
    }
}

int yunw_mesh_worker_start() {
    if(runCfg.mesh_enable){
        pthread_t pid;
        pthread_create(&pid, NULL, (void *)yunw_mesh_worker, NULL);
    }
}